package com.warom.sdg.webview.jsinterface;

import android.content.Context;
import android.util.Log;
import android.webkit.JavascriptInterface;

import com.warom.sdg.config.MeasurementPoint;
import com.warom.sdg.config.PlcMeasurementConfig;
import com.warom.sdg.config.PlcMeasurementUtils;
import com.warom.sdg.dto.VentilationControlDto;
import com.warom.sdg.dto.VentilationDataRequestDto;
import com.warom.sdg.enums.ModuleType;
import com.warom.sdg.model.ApiResponse;
import com.warom.sdg.model.DeviceType;
import com.warom.sdg.model.PlcDataEntity;
import com.warom.sdg.model.PlcDeviceEntity;
import com.warom.sdg.repository.PlcDeviceRepository;
import com.warom.sdg.service.PlcDataService;
import com.warom.sdg.util.LogUtils;
import com.warom.sdg.webview.BaseWebViewJsInterface;
import com.warom.sdg.webview.WebViewWrapper;
import com.warom.sdg.util.UserPreferencesManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * WebView JavaScript接口 - 通风控制
 * 处理通风控制相关的JavaScript调用
 */
public class WebViewJsVentilationInterface extends BaseWebViewJsInterface {
    private static final String TAG = "WebViewJsVentilation";

    // 数据服务
    private PlcDataService plcDataService;

    // 设备仓库
    private PlcDeviceRepository deviceRepository;

    private final List<Object> empty = new ArrayList<>();

    /**
     * 构造函数
     * 
     * @param context        上下文
     * @param webViewWrapper WebView包装类，用于回调
     */
    public WebViewJsVentilationInterface(Context context, WebViewWrapper webViewWrapper) {
        super(context, webViewWrapper);
        initRepositories(context);
    }

    /**
     * 构造函数
     * 
     * @param context 上下文
     */
    public WebViewJsVentilationInterface(Context context) {
        super(context, null);
        initRepositories(context);
    }

    /**
     * 初始化仓库
     * 
     * @param context 上下文
     */
    private void initRepositories(Context context) {
        deviceRepository = new PlcDeviceRepository(context);
    }

    /**
     * 获取设备仓库
     * 
     * @return 设备仓库
     */
    public PlcDeviceRepository getDeviceRepository() {
        return deviceRepository;
    }

    /**
     * 设置PLC数据服务
     * 
     * @param plcDataService PLC数据服务
     */
    public void setPlcDataService(PlcDataService plcDataService) {
        this.plcDataService = plcDataService;
    }

    /**
     * 获取通风系统数据
     * 
     * @param args      参数（可指定设备ID和类型）
     * @param requestId 请求ID
     */
    @JavascriptInterface
    public void getVentilationData(String args, String requestId) {
        executor.execute(() -> getVentilationData(args, result -> handleAsyncResponse(requestId, result)));
    }

    /**
     * 控制通风设备
     * 
     * @param args      参数（必须指定deviceType、deviceId和action）
     * @param requestId 请求ID
     */
    @JavascriptInterface
    public void controlVentilation(String args, String requestId) {
        executor.execute(() -> controlVentilation(args, result -> handleAsyncResponse(requestId, result)));
    }

    /**
     * 获取通风系统数据 (异步版本，用于内部实现)
     * 
     * @param argsJson 参数，可包含：
     *                 deviceId - 可选，设备ID
     *                 deviceSubType - 可选，设备类型 (butterfly_valve, axial_fan, etc.)
     * @param callback 回调函数，接收数据的JSON字符串
     */
    private void getVentilationData(String argsJson, Consumer<String> callback) {
        try {
            // 使用DTO对象解析请求参数
            VentilationDataRequestDto requestDto = gson.fromJson(argsJson, VentilationDataRequestDto.class);

            // 获取设备子类型
            String deviceSubType = requestDto.getDeviceSubType();

            LogUtils.logOperation("通风控制", "获取数据", "开始获取通风系统数据，设备类型: " +
                    (deviceSubType != null ? deviceSubType : "全部"));

            // 从配置中获取通风控制模块的测点数据
            Map<DeviceType, List<MeasurementPoint>> ventilationMap = PlcMeasurementConfig.moduleDevicePointsMap
                    .get(ModuleType.VENTILATION);

            if (ventilationMap == null || ventilationMap.isEmpty()) {
                // 如果没有配置通风控制测点，返回空数据但标记为成功
                ApiResponse<List<Object>> response = ApiResponse.success(empty);
                callback.accept(response.toJson());
                return;
            }

            // 获取所有设备类型的测点列表
            List<MeasurementPoint> allPoints = new ArrayList<>();
            for (DeviceType deviceTypeEnum : ventilationMap.keySet()) {
                List<MeasurementPoint> points = ventilationMap.get(deviceTypeEnum);
                if (points != null && !points.isEmpty()) {
                    for (MeasurementPoint point : points) {
                        // 如果测点是属性测点，则不添加到allPoints中
                        if (!PlcMeasurementUtils.isAttributePoint(point.getEnglishName())) {
                            if (deviceSubType == null || deviceSubType.equals(point.getDeviceSubType().toString())) {
                                allPoints.add(point);
                            }
                        }
                    }
                }
            }

            // 转换为前端需要的格式
            List<Map<String, Object>> resultList = new ArrayList<>();
            for (MeasurementPoint point : allPoints) {
                Map<String, Object> item = new HashMap<>();
                item.put("name", point.getName());
                item.put("englishName", point.getEnglishName());
                item.put("address", point.getAddress());
                item.put("unit", point.getUnit());
                item.put("description", point.getDescription());
                item.put("value", point.getValue());
                item.put("writeAddress", point.getWriteAddress());
                item.put("address2", point.getAddress2());
                item.put("writeAddress2", point.getWriteAddress2());
                List<PlcDataEntity> attributePoints = new ArrayList<>();
                //如果测点是属性测点，则需要获取属性测点的值
                if (point.getAttributePoints() != null && point.getAttributePoints().size() > 0) {
                    for (MeasurementPoint attributePoint : point.getAttributePoints()) {
                        boolean isFaultAlarm = PlcMeasurementUtils.isFaultAlarmPoint(attributePoint.getEnglishName());
                        boolean isRunningState = PlcMeasurementUtils
                                .isRunStatusPoint(attributePoint.getEnglishName());
                        if (isFaultAlarm) {
                            item.put("alarmState", attributePoint.getValue());
                        }
                        if (isRunningState) {
                            item.put("runState", attributePoint.getValue());
                        }
                    }
                    
                }

                resultList.add(item);
            }

            // 使用ApiResponse封装返回结果
            ApiResponse<List<Map<String, Object>>> response = ApiResponse.success(resultList);
            callback.accept(response.toJson());

        } catch (Exception e) {
            Log.e(TAG, "获取通风系统数据失败", e);
            LogUtils.logError("通风控制", "获取数据失败", e);
            callback.accept(ApiResponse.error("处理异常: " + e.getMessage()).toJson());
        }
    }

    /**
     * 控制通风设备 (异步版本，用于内部实现)
     * 
     * @param argsJson 参数JSON字符串
     * @param callback 回调函数，接收操作结果的JSON字符串
     */
    private void controlVentilation(String argsJson, Consumer<String> callback) {
        try {
            // 使用DTO对象解析请求参数
            VentilationControlDto controlDto = gson.fromJson(argsJson, VentilationControlDto.class);

            // 获取参数
            String deviceType = controlDto.getDeviceSubType();
            int deviceId = 0;
            // String deviceId = controlDto.getDeviceId();
            String action = controlDto.getAction();
            String pointAddress = controlDto.getPointAddress();
            boolean controlAll = controlDto.isControlAll();

            // 记录操作日志
            String operationDetail = controlAll ? "批量控制" + deviceType + "，操作：" + action
                    : "控制" + deviceType + "，操作：" + action + ",地址：" + pointAddress;

            LogUtils.logOperation("通风控制", "设备控制", operationDetail);

            // 获取通风控制模块的测点数据
            Map<DeviceType, List<MeasurementPoint>> ventilationMap = PlcMeasurementConfig.moduleDevicePointsMap
                    .get(ModuleType.VENTILATION);

            if (ventilationMap == null || ventilationMap.isEmpty()) {
                callback.accept(ApiResponse.error("未找到通风控制测点配置").toJson());
                return;
            }

            // 获取所有测点列表
            List<MeasurementPoint> allPoints = new ArrayList<>();
            for (DeviceType deviceTypeEnum : ventilationMap.keySet()) {
                List<MeasurementPoint> devicePoints = ventilationMap.get(deviceTypeEnum);
                // 这里我需要通过deviceType 获取当前设备类型为deviceType的设备ID
                int deviceTypeId = deviceTypeEnum.getId();
                // 在通过设备类型ID查找当前系统添加的plc设备为该类型的
                List<PlcDeviceEntity> deviceList = deviceRepository.listByDeviceTypeId(deviceTypeId);
                if (deviceList != null && !deviceList.isEmpty()) {
                    deviceId = deviceList.get(0).getDeviceId();
                }
                if (devicePoints != null && !devicePoints.isEmpty()) {
                    allPoints.addAll(devicePoints);
                }
            }

            if (allPoints.isEmpty()) {
                callback.accept(ApiResponse.error("未找到任何测点").toJson());
                return;
            }

            // 根据控制类型选择要控制的测点
            List<MeasurementPoint> pointsToControl = new ArrayList<>();

            if (controlAll) {
                // 批量控制 - 找出指定设备子类型的所有测点
                MeasurementPoint.DeviceSubType targetSubType = mapToPlcDeviceType(deviceType.toUpperCase());
                if (targetSubType == null) {
                    callback.accept(ApiResponse.error("无效的设备子类型: " + deviceType).toJson());
                    return;
                }

                for (MeasurementPoint point : allPoints) {
                    if (point.getDeviceSubType() == targetSubType) {
                        pointsToControl.add(point);
                    }
                }

                if (pointsToControl.isEmpty()) {
                    callback.accept(ApiResponse.error("未找到设备类型为" + deviceType + "的测点").toJson());
                    return;
                }

                Log.d(TAG, "批量控制 - 找到" + pointsToControl.size() + "个类型为" + deviceType + "的测点");
            } else {
                // 单设备控制 - 找到指定地址的测点
                MeasurementPoint targetPoint = null;
                for (MeasurementPoint point : allPoints) {
                    // 检查是否为自然通风窗类型
                    if (point.isNaturalWindow()) {
                        // 自然通风窗特殊处理，需要检查所有可能的地址
                        if (point.getAddress().equals(pointAddress) ||
                                point.getWriteAddress().equals(pointAddress) ||
                                point.getAddress2().equals(pointAddress) ||
                                point.getWriteAddress2().equals(pointAddress)) {
                            targetPoint = point;
                            break;
                        }
                    } else {
                        // 其他设备类型，只检查主地址和主写入地址
                        if (point.getAddress().equals(pointAddress) ||
                                (pointAddress != null && pointAddress.equals(point.getWriteAddress()))) {
                            targetPoint = point;
                            break;
                        }
                    }
                }
                if (targetPoint == null) {
                    callback.accept(ApiResponse.error("未找到地址为" + pointAddress + "的控制点").toJson());
                    return;
                }

                pointsToControl.add(targetPoint);
                Log.d(TAG, "单设备控制 - 找到测点: " + targetPoint.getName() + ", 地址: " + targetPoint.getAddress());
            }

            // 执行控制操作
            boolean success = controlDevices(pointsToControl, String.valueOf(deviceId), action);
            
            // 记录操作日志到SQLite数据库
            logDeviceControlOperation(deviceType, deviceId, action, controlAll, pointsToControl, success);
            
            // 返回结果
            if (success) {
                callback.accept(ApiResponse.success("操作成功").toJson());
            } else {
                callback.accept(ApiResponse.error("操作失败").toJson());
            }

        } catch (Exception e) {
            Log.e(TAG, "通风系统控制失败", e);
            LogUtils.logError("通风控制", "控制操作失败", e);
            callback.accept(ApiResponse.error("处理异常: " + e.getMessage()).toJson());
        }
    }

    /**
     * 记录设备控制操作日志到SQLite数据库
     * 
     * @param deviceType 设备类型
     * @param deviceId 设备ID
     * @param action 操作动作
     * @param controlAll 是否批量控制
     * @param pointsToControl 控制的测点列表
     * @param success 操作是否成功
     */
    private void logDeviceControlOperation(String deviceType, int deviceId, String action, 
                                          boolean controlAll, List<MeasurementPoint> pointsToControl, boolean success) {
        try {
            // 构建设备名称
            String deviceName = deviceType;
            if (!controlAll && pointsToControl != null && !pointsToControl.isEmpty()) {
                deviceName = pointsToControl.get(0).getName() + "(ID: " + deviceId + ")";
            }
            
            // 构建操作动作
            String actionDesc = "";
            if ("on".equals(action)) {
                actionDesc = "开启";
            } else if ("off".equals(action)) {
                actionDesc = "停止";
            } else if ("stop".equals(action)) {
                actionDesc = "关闭";
            } else {
                actionDesc = action;
            }
            
            // 构建错误信息
            String errorMessage = success ? "" : "操作失败";
            
            // 直接使用OperationLogService记录操作
            if (context != null) {
                try {
                    // 创建OperationLogService实例
                    com.warom.sdg.service.OperationLogService logService = 
                        new com.warom.sdg.service.OperationLogService(context);
                    
                    // 获取当前用户名
                    String username = getCurrentUsername();
                    
                    // 直接调用logDeviceControl方法记录操作日志
                    logService.logDeviceControl(
                        username,
                        deviceName,
                        actionDesc,
                        success ? "SUCCESS" : "FAILED",
                        errorMessage
                    );
                    
                    Log.d(TAG, "已记录设备控制操作日志: " + deviceName + ", 操作: " + actionDesc + ", 结果: " + (success ? "成功" : "失败"));
                } catch (Exception e) {
                    Log.e(TAG, "记录操作日志到SQLite失败", e);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "记录操作日志到SQLite出错", e);
        }
    }
    
    /**
     * 获取当前用户名
     * 
     * @return 当前用户名
     */
    private String getCurrentUsername() {
        // 从UserPreferencesManager获取当前用户名
        String username = UserPreferencesManager.getCurrentUsername(context);
        if (username == null) {
            username = "admin"; // 如果未找到用户名，则默认返回admin
        }
        return username;
    }

    /**
     * 控制设备（支持单个或多个测点）
     * 
     * @param points   要控制的测点列表
     * @param deviceId 设备ID
     * @param action   操作类型（on, off, stop）
     * @return 是否成功
     */
    public boolean controlDevices(List<MeasurementPoint> points, String deviceId, String action) {
        try {
            if (points == null || points.isEmpty()) {
                Log.e(TAG, "测点列表为空");
                return false;
            }

            // 确定控制值
            int controlValue = 0;
            if ("on".equals(action)) {
                controlValue = 1;
            } else if ("off".equals(action)) {
                controlValue = 0;
            } else if ("stop".equals(action)) {
                controlValue = 2; // 假设2表示停止
            }

            // 执行写入操作
            if (plcDataService == null) {
                Log.e(TAG, "PLC数据服务未初始化");
                return false;
            }

            boolean allSuccess = true;

            // 对每个测点执行控制
            for (MeasurementPoint point : points) {
                // 如果没有指定设备ID，使用默认值1
                String targetDeviceId = (deviceId != null && !deviceId.isEmpty()) ? deviceId : "1";

                // 确定要使用的地址
                String controlAddress = point.getAddress(); // 默认使用读取地址

                // 根据设备类型和操作选择合适的地址
                if (point.isNaturalWindow()) {
                    // 自然通风窗特殊处理
                    if ("on".equals(action)) {
                        // 开窗操作 - 使用主写入地址
                        controlAddress = point.getWriteAddress();
                        Log.d(TAG, "自然通风窗开窗操作，使用地址: " + controlAddress);
                    } else if ("off".equals(action)) {
                        // 关窗操作 - 使用第二写入地址
                        controlAddress = point.getWriteAddress2();
                        Log.d(TAG, "自然通风窗关窗操作，使用地址: " + controlAddress);
                    }
                    // 自然通风窗始终是on,
                    controlValue = 1;
                } else {
                    // 其他设备类型 - 如果有写地址则使用写地址
                    if (point.hasWriteAddress()) {
                        controlAddress = point.getWriteAddress();
                    }
                }

                // 使用PlcDataService写入值
                if (!plcDataService.writeAddress(targetDeviceId, controlAddress, controlValue)) {
                    Log.e(TAG, "控制测点失败: " + point.getName() + ", 地址: " + controlAddress);
                    allSuccess = false;
                } else {
                    Log.d(TAG, "控制测点成功: " + point.getName() + ", 地址: " + controlAddress + ", 值: " + controlValue);
                    // 更新缓存中的测点状态值
                    point.setValue((double) controlValue);
                    Log.d(TAG, "已更新测点缓存状态: " + point.getName() + ", 新值: " + controlValue);
                }
            }

            return allSuccess;

        } catch (Exception e) {
            Log.e(TAG, "控制设备失败", e);
            return false;
        }
    }

    /**
     * 将前端设备类型映射到PLC测点设备类型
     * 
     * @param deviceType 前端设备类型
     * @return PLC设备类型
     */
    private MeasurementPoint.DeviceSubType mapToPlcDeviceType(String deviceType) {
        switch (deviceType) {
            case "BUTTERFLY_VALVE":
                return MeasurementPoint.DeviceSubType.BUTTERFLY_VALVE;
            case "AXIAL_FAN":
                return MeasurementPoint.DeviceSubType.AXIAL_FAN;
            case "CIRCULATION_FAN":
                return MeasurementPoint.DeviceSubType.CIRCULATION_FAN;
            case "FUMIGATION_FAN":
                return MeasurementPoint.DeviceSubType.FUMIGATION_FAN;
            case "NATURAL_WINDOW":
                return MeasurementPoint.DeviceSubType.NATURAL_WINDOW;
            default:
                return null;
        }
    }
} 